﻿using Common.Utils;
using ReactiveUI.Fody.Helpers;
using ReactiveUI;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Reactive;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Controls.Primitives;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows;
using System.IO;

namespace Common.ViewModels
{
    public class ReflexBuildControl
    {

        public static void AddWindow(object dataContext)
        {
            if (dataContext == null)
            {
                return;
            }
            Window window = new Window();
            UniformGrid uniform = new UniformGrid() { Columns = 4, VerticalAlignment = VerticalAlignment.Top };
            window.Content = uniform;
            dynamic name = dataContext;
            Type type = dataContext.GetType();
            var xmlCommentHelper = new XmlCommentHelper();
            var assemblyName = type.Assembly.ManifestModule.Name;
            string xml = $"{assemblyName.Substring(0, assemblyName.Length - 4)}.xml";
            if (File.Exists(xml))
            {
                xmlCommentHelper.Load(xml);
            }
            else
            {
                xmlCommentHelper.Load($"ImportModulePath//{xml}");
            }
            ReflexBuildControl.AddBase(uniform, dataContext, type, xmlCommentHelper);
            ReflexBuildControl.AddMeth(uniform, dataContext, type, xmlCommentHelper);
            触发查找(window, uniform);
            try
            {
                window.Title = name.Name;
            }
            catch (Exception ex)
            {

            }

            window.Show();
        }

        public static void 触发查找(Window window, UniformGrid uniform)
        {
            window.KeyUp += ((sender, e) =>
            {
                if (e.Key == Key.F && Keyboard.Modifiers == ModifierKeys.Control)
                {
                    Window findWindow = new Window() { SizeToContent = SizeToContent.WidthAndHeight, WindowStartupLocation = WindowStartupLocation.CenterOwner };
                    StackPanel panel = new StackPanel() { Orientation = Orientation.Horizontal, HorizontalAlignment = HorizontalAlignment.Stretch };
                    findWindow.Content = panel;
                    findWindow.Owner = window;
                    Button button = new Button() { Content = "确认" };
                    TextBox txt = new TextBox() { MinWidth = 100, Height = 30 };
                    panel.Children.Add(txt);
                    panel.Children.Add(button);
                    button.Click += ((sender, args) =>
                    {
                        //var un=  uniform 
                        //    Vis
                        var visuals = VisualHelp.GetChildrens(uniform);


                        foreach (var uiElement in visuals)
                        {
                            if (uiElement is CheckBox checkBox)
                            {
                                if (checkBox.Content.ToString().Contains(txt.Text))
                                {
                                    checkBox.Foreground = Brushes.Red;
                                    checkBox.FontSize += 20;
                                }

                                if (checkBox.ToolTip != null && checkBox.ToolTip.ToString().Contains(txt.Text))
                                {
                                    checkBox.Foreground = Brushes.Red;
                                    checkBox.FontSize += 20;
                                }
                                continue;
                            }

                            if (uiElement is TextBox textBox)
                            {
                                if (textBox.Text.ToString().Contains(txt.Text))
                                {
                                    textBox.Foreground = Brushes.Red;
                                    textBox.FontSize += 20;
                                }

                                if (textBox.ToolTip != null && textBox.ToolTip.ToString().Contains(txt.Text))
                                {
                                    textBox.Foreground = Brushes.Red;
                                    textBox.FontSize += 20;
                                }
                            }

                            if (uiElement is TextBlock textBlock)
                            {
                                if (textBlock.Text.ToString().Contains(txt.Text))
                                {
                                    textBlock.Foreground = Brushes.Red;
                                    textBlock.FontSize = textBlock.FontSize + 20;
                                }

                                if (textBlock.ToolTip != null && textBlock.ToolTip.ToString().Contains(txt.Text))
                                {
                                    textBlock.Foreground = Brushes.Red;
                                    textBlock.FontSize = textBlock.FontSize + 20;

                                }
                            }

                        }
                    });
                    findWindow.ShowDialog();
                }

            });

            //window.KeyUp += Window_KeyUp;




        }

        private static void Window_KeyUp(object sender, KeyEventArgs e)
        {
            //throw new NotImplementedException();
        }

        public static void AddBase<T>(UniformGrid root, T t)
        {

            AddBase<T>(root, t, GetXmlCommentHelper<T>());
        }

        public static XmlCommentHelper GetXmlCommentHelper<T>()
        {
            var xmlCommentHelper = new XmlCommentHelper();
            Type type = typeof(T);
            var assemblyName = type.Assembly.ManifestModule.Name;
            string xml = $"{assemblyName.Substring(0, assemblyName.Length - 4)}.xml";
            xmlCommentHelper.Load(xml);
            return xmlCommentHelper;
        }

        public static void AddBase<T>(UniformGrid root, T t, XmlCommentHelper xmlCommentHelper)
        {
            Type type = t.GetType();
            AddBase(root, t, type, xmlCommentHelper);
        }

        public static void AddBase(UniformGrid root, object t, Type type, XmlCommentHelper xmlCommentHelper, int level = 0)
        {
            if (t == null)
            {
                return;
            }

            if (level > 3)
            {
                return;
            }

            var properties = type.GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < properties.Length; i++)
            {

                var property = properties[i];
                var reportLevelAttribute = (ReactiveAttribute?)Attribute.GetCustomAttribute(property, typeof(ReactiveAttribute));



                if (reportLevelAttribute == null && !(property.CanRead && property.CanWrite))
                {
                    continue;
                }



                string comment = xmlCommentHelper.GetFieldOrPropertyComment(property);

                if (property.PropertyType == typeof(bool))
                {
                    CheckBox checkBox = new CheckBox();
                    if (string.IsNullOrEmpty(comment) || comment.Length > 14)
                    {
                        checkBox.Content = property.Name;
                        checkBox.ToolTip = comment;
                    }
                    else
                    {
                        checkBox.Content = xmlCommentHelper.GetFieldOrPropertyComment(property);
                        checkBox.ToolTip = property.Name;
                    }



                    Binding binding = new Binding(property.Name);
                    binding.Source = t;
                    binding.Mode = BindingMode.TwoWay;
                    checkBox.SetBinding(CheckBox.IsCheckedProperty, binding);

                    root.Children.Add(checkBox);
                }
                else if (property.PropertyType.IsEnum)
                {
                    StackPanel stackPanel = new StackPanel();
                    stackPanel.Orientation = Orientation.Horizontal;
                    TextBlock textBlock = new TextBlock();
                    textBlock.Margin = new Thickness(0, 0, 5, 0);

                    ComboBox combobox = new ComboBox();
                    stackPanel.Children.Add(textBlock);
                    stackPanel.Children.Add(combobox);
                    combobox.ItemsSource = Enum.GetValues(property.PropertyType);
                    if (string.IsNullOrEmpty(comment) || comment.Length > 14)
                    {
                        textBlock.Text = property.Name;
                        stackPanel.ToolTip = comment;
                    }
                    else
                    {
                        textBlock.Text = xmlCommentHelper.GetFieldOrPropertyComment(property);
                        stackPanel.ToolTip = property.Name;
                    }

                    Binding binding = new Binding(property.Name);
                    binding.Source = t;
                    binding.Mode = BindingMode.TwoWay;
                    combobox.SetBinding(ComboBox.SelectedValueProperty, binding);
                    root.Children.Add(stackPanel);
                }
                else if (property.PropertyType.IsValueType || property.PropertyType == typeof(string))
                {
                    StackPanel stackPanel = new StackPanel();
                    stackPanel.Orientation = Orientation.Horizontal;
                    TextBlock textBlock = new TextBlock();
                    textBlock.Margin = new Thickness(0, 0, 5, 0);
                    TextBox textBox = new TextBox();
                    stackPanel.Children.Add(textBlock);
                    stackPanel.Children.Add(textBox);
                    textBox.MinWidth = 50;
                    if (string.IsNullOrEmpty(comment) || comment.Length > 14)
                    {
                        textBlock.Text = property.Name;
                        stackPanel.ToolTip = comment;
                    }
                    else
                    {
                        textBlock.Text = xmlCommentHelper.GetFieldOrPropertyComment(property);
                        stackPanel.ToolTip = property.Name;
                    }

                    Binding binding = new Binding(property.Name);
                    binding.Source = t;
                    binding.Mode = BindingMode.TwoWay;
                    textBox.SetBinding(TextBox.TextProperty, binding);
                    root.Children.Add(stackPanel);
                }
                else
                {
                    if (!property.PropertyType.IsClass)
                    {
                        continue;
                    }

                    if (!typeof(INotifyPropertyChanged).IsAssignableFrom(property.PropertyType))
                    {
                        continue;
                    }


                    TextBlock textBlock = new TextBlock();
                    textBlock.Margin = new Thickness(0, 0, 5, 0);
                    textBlock.Foreground = Brushes.Salmon;
                    textBlock.FontWeight = FontWeights.Bold;
                    textBlock.FontSize = 20;
                    if (string.IsNullOrEmpty(comment) || comment.Length > 14)
                    {
                        textBlock.Text = property.Name;
                        textBlock.ToolTip = comment;
                    }
                    else
                    {
                        textBlock.Text = xmlCommentHelper.GetFieldOrPropertyComment(property);
                        textBlock.ToolTip = property.Name;
                    }


                    root.Children.Add(textBlock);
                    object value = property.GetValue(t);
                    if (value == null)
                    {
                        continue;
                    }

                    //详情
                    Button button = new Button() { HorizontalAlignment = HorizontalAlignment.Left };
                    button.Content = textBlock.Text + "详情";
                    button.Click += (x, y) =>
                    {
                        Window window = new Window();
                        UniformGrid uniform = new UniformGrid()
                        {
                            VerticalAlignment = VerticalAlignment.Top,
                            Columns = 4,
                        };
                        window.Content = uniform;
                        ReflexBuildControl.AddBase(uniform, value, property.PropertyType, xmlCommentHelper);
                        window.Show();
                    };
                    root.Children.Add(button);


                }

            }
        }



        //public Control GetControlFromMember(MemberInfo member,string comment,Type type) 
        //{

        //}


        public static void AddCommand<T>(UniformGrid root, T t)
        {
            var xmlCommentHelper = GetXmlCommentHelper<T>();
            Type type = t.GetType();
            AddCommand(root, t, type, xmlCommentHelper);
        }

        public static void AddCommand(UniformGrid root, object t, Type type, XmlCommentHelper xmlCommentHelper)
        {
            var properties = type.GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
            Type typeReactiveCommand = typeof(ReactiveCommand<,>);
            foreach (var property in properties)
            {
                string comment = xmlCommentHelper.GetFieldOrPropertyComment(property);
                if (property.PropertyType.IsGenericType)
                {
                    Type type1 = property.PropertyType.GetGenericTypeDefinition();
                    if (typeReactiveCommand.IsAssignableFrom(type1))
                    {
                        var arguments = property.PropertyType.GetGenericArguments();
                        if (arguments.Length != 2)
                        {
                            continue;
                        }

                        if (arguments[0] == typeof(bool))
                        {
                            CheckBox checkBox = new CheckBox();
                            if (string.IsNullOrEmpty(comment) || comment.Length > 14)
                            {
                                checkBox.Content = property.Name;
                                checkBox.ToolTip = comment;
                            }
                            else
                            {
                                checkBox.Content = xmlCommentHelper.GetFieldOrPropertyComment(property);
                                checkBox.ToolTip = property.Name;
                            }



                            Binding binding = new Binding(property.Name);
                            binding.Source = t;
                            binding.Mode = BindingMode.OneWay;
                            checkBox.SetBinding(CheckBox.CommandProperty, binding);

                            Binding binding1 = new Binding(nameof(CheckBox.IsChecked));
                            binding1.Source = checkBox;
                            binding1.Mode = BindingMode.OneWay;
                            checkBox.SetBinding(CheckBox.CommandParameterProperty, binding1);

                            root.Children.Add(checkBox);
                        }


                        if (arguments[0] == typeof(Unit))
                        {
                            Button button = new Button();
                            if (string.IsNullOrEmpty(comment) || comment.Length > 14)
                            {
                                button.Content = property.Name;
                                button.ToolTip = comment;
                            }
                            else
                            {
                                button.Content = xmlCommentHelper.GetFieldOrPropertyComment(property);
                                button.ToolTip = property.Name;
                            }

                            Binding binding = new Binding(property.Name);
                            binding.Source = t;
                            binding.Mode = BindingMode.OneWay;
                            button.SetBinding(Button.CommandProperty, binding);
                            root.Children.Add(button);
                        }

                    }
                }


            }
        }

        public static void AddMeth<T>(UniformGrid root, T t)
        {
            Type type = t.GetType();
            var xmlCommentHelper = GetXmlCommentHelper<T>();
            AddMeth(root, t, type, xmlCommentHelper);
        }

        /// <summary>
        /// 添加函数
        /// </summary>
        /// <param name="root"></param>
        /// <param name="t"></param>
        /// <param name="type"></param>
        /// <param name="xmlCommentHelper"></param>
        public static void AddMeth(UniformGrid root, object t, Type type, XmlCommentHelper xmlCommentHelper)
        {
            MethodInfo[] methodInfos = type.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static);
            foreach (MethodInfo methodInfo in methodInfos)
            {
                if (methodInfo.DeclaringType != type)
                {
                    continue;
                }

                if (methodInfo.Attributes.HasFlag(MethodAttributes.SpecialName))
                {
                    continue;
                }

                if (methodInfo.IsDefined(typeof(CompilerGeneratedAttribute)))
                {
                    continue;
                }

                var parameterInfos = methodInfo.GetParameters();


                if (parameterInfos.Length > 1)
                {
                    continue;
                }


                string comment = xmlCommentHelper.GetMethodComment(methodInfo);
                (string Content, string ToolTip) descript = GetContent(methodInfo.Name, comment);
                Button button = new Button();
                button.Content = descript.Content;
                button.ToolTip = descript.ToolTip;


                if (parameterInfos.Length == 1)
                {

                    StackPanel stackPanel = new StackPanel() { Orientation = Orientation.Horizontal };

                    //引用类型
                    if (parameterInfos[0].ParameterType == typeof(bool))
                    {
                        CheckBox checkBox = new CheckBox() { Content = $"{descript.Content}入参:" };
                        stackPanel.Children.Add(checkBox);
                        root.Children.Add(stackPanel);
                        root.Children.Add(button);
                        button.Click += (sender, e) =>
                        {
                            if (methodInfo.IsStatic)
                            {
                                methodInfo.Invoke(null, new object[] { checkBox.IsChecked });

                            }
                            else
                            {
                                methodInfo.Invoke(t, new object[] { checkBox.IsChecked });
                            }
                        };
                    }
                    else if (parameterInfos[0].ParameterType.IsEnum)
                    {
                        TextBlock textBlock = new TextBlock() { Text = $"{descript.Content}入参:" };
                        stackPanel.Children.Add(textBlock);
                        ComboBox combobox = new ComboBox();
                        stackPanel.Children.Add(combobox);
                        root.Children.Add(stackPanel);
                        combobox.ItemsSource = Enum.GetValues(parameterInfos[0].ParameterType);
                        root.Children.Add(button);
                        button.Click += (sender, e) =>
                        {
                            if (methodInfo.IsStatic)
                            {
                                methodInfo.Invoke(null, new object[] { combobox.SelectedValue });

                            }
                            else
                            {
                                methodInfo.Invoke(t, new object[] { combobox.SelectedValue });
                            }
                        };
                    }
                    else if (parameterInfos[0].ParameterType == typeof(string) || parameterInfos[0].ParameterType.IsValueType)
                    {
                        TextBlock textBlock = new TextBlock() { Text = $"{descript.Content}入参:" };
                        stackPanel.Children.Add(textBlock);
                        TextBox textBox = new TextBox() { MinWidth = 50 };
                        stackPanel.Children.Add(textBox);
                        root.Children.Add(stackPanel);
                        root.Children.Add(button);
                        button.Click += (sender, e) =>
                        {
                            if (methodInfo.IsStatic)
                            {
                                methodInfo.Invoke(null, new object[] { textBox.Text });

                            }
                            else
                            {
                                methodInfo.Invoke(t, new object[] { textBox.Text });
                            }
                        };
                    }
                    else
                    {
                        continue;
                    }

                }

                if (parameterInfos.Length == 0)
                {
                    button.Click += (sender, e) =>
                    {
                        if (methodInfo.IsStatic)
                        {
                            methodInfo.Invoke(null, null);

                        }
                        else
                        {
                            methodInfo.Invoke(t, null);
                        }

                    };


                    root.Children.Add(button);
                }
            }

            type.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static);
        }


        public static (string Content, string ToolTip) GetContent(string name, string comment)
        {
            (string Content, string ToolTip) button;
            if (string.IsNullOrEmpty(comment) || comment.Length > 14)
            {
                button.Content = name;
                button.ToolTip = comment;
            }
            else
            {
                button.Content = comment;
                button.ToolTip = comment;
            }
            return button;
        }

        public static void AddBaseWithoutReactive<T>(UniformGrid root, T t)
        {
            //root.DataContext = t;
            var xmlCommentHelper = new XmlCommentHelper();
            Type type = t.GetType();
            var assemblyName = type.Assembly.ManifestModule.Name;
            string xml = $"{assemblyName.Substring(0, assemblyName.Length - 4)}.xml";
            string xmlPath = "SprayingRobot.ViewModel.xml";
            string path = AppDomain.CurrentDomain.BaseDirectory + xml;
            xmlCommentHelper.Load(xml);
            var properties = type.GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < properties.Length; i++)
            {

                var property = properties[i];
                //var reportLevelAttribute = (ReactiveAttribute?)Attribute.GetCustomAttribute(property, typeof(ReactiveAttribute));
                //if (reportLevelAttribute == null)
                //{
                //    continue;
                //}
                string comment = xmlCommentHelper.GetFieldOrPropertyComment(property);

                if (property.PropertyType == typeof(bool))
                {
                    CheckBox checkBox = new CheckBox();
                    if (string.IsNullOrEmpty(comment) || comment.Length > 14)
                    {
                        checkBox.Content = property.Name;
                        checkBox.ToolTip = comment;
                    }
                    else
                    {
                        checkBox.Content = xmlCommentHelper.GetFieldOrPropertyComment(property);
                        checkBox.ToolTip = property.Name;
                    }



                    Binding binding = new Binding(property.Name);
                    //binding.Source = t;
                    binding.Mode = BindingMode.TwoWay;
                    checkBox.SetBinding(CheckBox.IsCheckedProperty, binding);

                    root.Children.Add(checkBox);
                }
                else
                {
                    StackPanel stackPanel = new StackPanel();
                    stackPanel.Orientation = Orientation.Horizontal;
                    TextBlock textBlock = new TextBlock();
                    textBlock.Margin = new Thickness(0, 0, 5, 0);
                    TextBox textBox = new TextBox();
                    stackPanel.Children.Add(textBlock);
                    stackPanel.Children.Add(textBox);
                    textBox.MinWidth = 50;
                    if (string.IsNullOrEmpty(comment) || comment.Length > 14)
                    {
                        textBlock.Text = property.Name;
                        stackPanel.ToolTip = comment;
                    }
                    else
                    {
                        textBlock.Text = xmlCommentHelper.GetFieldOrPropertyComment(property);
                        stackPanel.ToolTip = property.Name;
                    }

                    Binding binding = new Binding(property.Name);
                    //binding.Source = t;
                    binding.Mode = BindingMode.TwoWay;
                    textBox.SetBinding(TextBox.TextProperty, binding);
                    root.Children.Add(stackPanel);
                }

            }

            //MessageBox.Show(root.Children.Count.ToString());
        }
    }
}
